package com.fire.chat.service.impl;


import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fire.chat.cache.AuthorityCacheStrategy;
import com.fire.chat.constant.CacheConstant;
import com.fire.chat.dao.SysRoleMapper;
import com.fire.chat.entity.bo.SysRoleBO;
import com.fire.chat.entity.po.SysMenu;
import com.fire.chat.entity.po.SysRole;
import com.fire.chat.entity.po.SysRoleMenuRef;
import com.fire.chat.entity.po.SysUserRoleRef;
import com.fire.chat.entity.vo.SysMenuVO;
import com.fire.chat.entity.vo.SysRoleVO;
import com.fire.chat.exception.BusinessException;
import com.fire.chat.service.SysRoleMenuRefService;
import com.fire.chat.service.SysRoleService;
import com.fire.chat.service.SysUserRoleRefService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>标题: 角色表 Service 实现类</p>
 * <p>描述: </p>
 * <p>版权: Copyright (c) 2020</p>
 *
 * @version: 1.0
 * @author: xiejiarong
 * @date 2020-11-04
 */
@Service
public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> implements SysRoleService {

    @Autowired
    SysRoleMenuRefService roleMenuRefService;

    @Autowired(required = false)
    AuthorityCacheStrategy authorityCacheStrategy;

    @Autowired
    SysMenuServiceImpl sysMenuService;

    @Autowired
    SysUserRoleRefService sysUserRoleRefService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addRole(SysRoleBO role) {
        SysRole insertParam=new SysRole();
        BeanUtils.copyProperties(role,insertParam);
        super.save(insertParam);
        roleMenuRefService.saveBatch(getRefByRecur(role,insertParam.getId()));
    }

    /**
     *
     * @return void
     * @author xiejr
     * @description: 角色列表
     * @date 2020/11/9 10:53
     */

    @Override
    public List<SysRoleVO> roleList() {
        List<SysRoleVO> simpleRoleWithMenus = this.getBaseMapper().findSimpleRoleWithMenus();
        simpleRoleWithMenus.forEach(data->{
            List<SysMenuVO> menus=sysMenuService.transferMenuVo(data.getMenus().stream().map(menu->
            {
                SysMenu build = SysMenu.builder().level(menu.getLevel()).iconUrl(menu.getIconUrl()).isDelete(0).nodeType(menu.getNodeType()).parentId(menu.getParentId())
                        .menuCode(menu.getMenuCode()).name(menu.getName()).linkUrl(menu.getLinkUrl()).build();
                build.setId(menu.getId());
                return build;
            })
                    .collect(Collectors.toList()), CacheConstant.PARENT_ROOT_ID);
            data.setMenus(menus);
        });
        return simpleRoleWithMenus;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateRole(SysRoleBO role) {
        if (role.getId()==null){
            throw new BusinessException("修改角色必须传递该角色ID");
        }
        SysRole insertParam=new SysRole();
        BeanUtils.copyProperties(role,insertParam);
        //先删除该角色下的所有资源
        roleMenuRefService.remove(Wrappers.<SysRoleMenuRef>lambdaUpdate().eq(SysRoleMenuRef::getRoleId,role.getId()));
        //递归组装前端传递过来的当前角色的最新资源权限
        List<SysRoleMenuRef> refByRecur = getRefByRecur(role, role.getId());
        roleMenuRefService.saveBatch(refByRecur);
        super.saveOrUpdate(insertParam);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteRole(String roleId) {
        Long id=Long.valueOf(roleId);
        //物理删除该角色下的所有资源关联记录和用户关联记录
        roleMenuRefService.remove(Wrappers.<SysRoleMenuRef>lambdaUpdate().eq(SysRoleMenuRef::getRoleId,id));
        sysUserRoleRefService.remove(Wrappers.<SysUserRoleRef>lambdaUpdate().eq(SysUserRoleRef::getRoleId,id));
        //逻辑删除该角色
        SysRole sysRole=new SysRole();
        sysRole.setId(id);
        sysRole.setIsDelete(1);
        super.updateById(sysRole);
    }

    /**
     *
     * @param role 角色业务对象
    	 * @param roleId 角色ID
     * @return java.util.List<cn.com.hwqh.entity.model.SysRoleMenuRef>
     * @author xiejr
     * @description: 组装单个角色的资源
     * @date 2020/11/9 15:32
     */

    private List<SysRoleMenuRef> getRefByRecur(SysRoleBO role,Long roleId){
        Set<Long> menuIds = new HashSet<>();
        //组装该用户的权限
        if (CollectionUtils.isNotEmpty(role.getMenus())){
            menuIds.addAll(role.getMenus());
        }
        List<SysRoleMenuRef> roleMenuRefs=new ArrayList<>(menuIds.size());
        SysRoleMenuRef sysRoleMenuRef=null;
        Iterator<Long> iterator=menuIds.iterator();
        while (iterator.hasNext()){
            sysRoleMenuRef=new SysRoleMenuRef();
            sysRoleMenuRef.setRoleId(roleId);
            sysRoleMenuRef.setMenuId(iterator.next());
            roleMenuRefs.add(sysRoleMenuRef);
        }
        return roleMenuRefs;
    }
}
